/*
 * Graphics.cpp
 *
 *  Created on: 10/07/2010
 *      Author: Nenem
 */

#include "Graphics.h"

Graphics::Graphics() {
	RESOLUTION_X = 640;
	RESOLUTION_Y = 480;

	Screen = SDL_SetVideoMode(RESOLUTION_X, RESOLUTION_Y, BITSPERPIXEL, SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_RESIZABLE);
	if (Screen == NULL) {
		cout << "Could not set this Video mode: " << SDL_GetError();
	}
}

Graphics::~Graphics() {
	SDL_FreeSurface(Screen);
}

void Graphics::Draw(int x, int y, SDL_Surface *layerA, SDL_Surface *layerB){
	sortVector();

	SDL_FillRect( Screen, NULL, 0 );

	/*
	 * Create a SDL_Surface, copy of layerA
	 * Blit on this surface and blit this surface on Screen at the end
	 */
//	SDL_Surface *surface = SDL_CreateRGBSurface(layerA->flags, layerA->w, layerA->h, Screen->format->BitsPerPixel,
//			Screen->format->Rmask, Screen->format->Gmask, Screen->format->Bmask, Screen->format->Amask);
	SDL_Rect surfaceRect;
	surfaceRect.w = RESOLUTION_X;
	surfaceRect.h = RESOLUTION_Y;
	surfaceRect.x = x;
	surfaceRect.y = y;

	SDL_BlitSurface(layerA, &surfaceRect, Screen, NULL);

	for(unsigned int i = 0; i <sprites.size() ; i++) {
		SDL_Rect *srcrect, *dstrect;
		srcrect = new SDL_Rect();
		dstrect = new SDL_Rect();
		srcrect->w = sprites[i]->getW();
		srcrect->h = sprites[i]->getH();
		srcrect->x = sprites[i]->getX();
		srcrect->y = sprites[i]->getY();
		dstrect->x = sprites[i]->getRelPos().x - x;
		dstrect->y = sprites[i]->getRelPos().y - y;

		SDL_BlitSurface(sprites[i]->getImage(), srcrect, Screen, dstrect);
	}

	SDL_BlitSurface(layerB, &surfaceRect, Screen, NULL);

//	SDL_BlitSurface(surface, surfaceRect, Screen, NULL);
	sprites.clear();
}

void Graphics::updateScreen(){
	SDL_UpdateRect(Screen, 0, 0, 0, 0);
}

void Graphics::addImage(Image *image){
	sprites.push_back(image);
}

bool compareSprites(Image *A, Image *B){
	return A->getRealPos().y < B->getRealPos().y ;
}
//
//
void Graphics::sortVector(){
	sort(sprites.begin(), sprites.end(), compareSprites);
}

void Graphics::getTalkSurface(string text){
	TTF_Init();
	TTF_Font *fnt = TTF_OpenFont((getPath() + "Fonts\\BLKCHCRY.ttf").c_str(), 24 );
	SDL_Color clrFg = {255,255,255,0};  //
	SDL_Color clrBg = {255,255,255,0};
	SDL_Rect rcDest = {0,0,0,0};
	SDL_Surface *dialog = IMG_Load((getPath() + "Misc\\dialog.png").c_str());
	PrintStrings(dialog, fnt, text, rcDest, clrFg, clrBg);
	SDL_Rect rcDialog;
	SDL_Rect rcDialog2;
	rcDialog = newSDL_Rect(0,0,640,320);
	rcDialog2.x = 0;
	rcDialog2.y = 320;
	SDL_BlitSurface(dialog,&rcDialog,Screen,&rcDialog2);
	SDL_FreeSurface(dialog);
	TTF_CloseFont( fnt );
	TTF_Quit();
}

/* Make an SDL_Rect without manually setting each value one at a time */
SDL_Rect newSDL_Rect( int xs,int ys, int dx,int dy ) {
	SDL_Rect rc;
	rc.x = xs; rc.y = ys;
	rc.w = dx; rc.h = dy;
	return( rc );
}
/* Make a new SDL_Color */
SDL_Color newSDL_Color( int r, int g, int b, int a ) {
	SDL_Color clr;
	clr.r = r;
	clr.g = g;
	clr.b = b;
	clr.unused = a;
	return( clr );
}
/* Who needs alpha anyway? */
SDL_Color newSDL_Color( int r, int g, int b ) {
	SDL_Color clr;
	clr.r = r;
	clr.g = g;
	clr.b = b;
	clr.unused = 0;
	return( clr );
}
/* operators are fun */
bool operator==(SDL_Color a, SDL_Color b) {
	return( a.r == b.r && a.g == b.g && a.b == b.b );
}
bool operator!=(SDL_Color a, SDL_Color b) {
	return( ( a.r != b.r || a.g != b.g || a.b != b.b ) );
}
/* It's faster to type this way */
int SDL_MapRGB( SDL_PixelFormat *format, SDL_Color clr ) {
	return( SDL_MapRGB( format, clr.r, clr.g, clr.b ) );
}
/* Same here */
int SDL_FillRect( SDL_Surface *dest, SDL_Rect *rc, SDL_Color &clr ) {
	if( dest == NULL ) {  return(-1);  }
	return( SDL_FillRect( dest, rc, SDL_MapRGB( dest->format, clr ) ) );
}

void PrintStrings( SDL_Surface *sDest, TTF_Font *fnt, string str,
                   SDL_Rect &rc, SDL_Color clrFg, SDL_Color clrBg ) {
  int lineSkip = TTF_FontLineSkip( fnt );  // Get the line-skip value.
  int width = 0, height = 10;
  vector<string> vLines; // these are the individual lines.

  // Break the String into its lines:
  int n = 0;
  while( n != -1 ) {
    // Get until either '\n' or '\0':
    string strSub;
    n = str.find( '\n', 0 ); // Find the next '\n'
    strSub = str.substr( 0,n );
    if( n != -1 ) {
      str = str.substr( n+1, -1 );
    }
    vLines.push_back(strSub);

    // Get the size of the rendered text:
    int w = 0;
    TTF_SizeText( fnt, strSub.c_str(), &w,&height );
    if( w > width ) {  width = w;  }
    // (really, we just want to see how wide this is going to be)
  }

  // Since the width was determined earlier, get the height:
  // (vLines.size() == Number of Lines)
  height = (vLines.size()-1) * lineSkip + height; // plus the first line
  // (we assume that height is the same for all lines.)

  // Make the surface to which to blit the text:
  SDL_Surface *sText;
  sText = SDL_CreateRGBSurface( SDL_SWSURFACE, width,height,
      sDest->format->BitsPerPixel,
      sDest->format->Rmask,
      sDest->format->Gmask,
      sDest->format->Bmask,
      sDest->format->Amask
  );
  // (it's compatible with the destination Surface

  // Now, fill it with the background color:
  //SDL_FillRect( sText,NULL, clrBg );

  // Actually render the text:
  SDL_Surface *sTemp = NULL;
  for( unsigned int i = 0; i < vLines.size(); i++ ) {
    // The rendered text:
    sTemp = TTF_RenderText_Solid( fnt, vLines[i].c_str(), clrFg );
    SDL_Rect rcTemp = newSDL_Rect(0,i*lineSkip,0,0);
    // Put it on the surface (sText):
    SDL_BlitSurface( sTemp,NULL,
      sText,&rcTemp );
  // Clean up:
  SDL_FreeSurface( sTemp );
  }
  // So, now we have a nice bitmap (sText) that has all the text on it.

  // Draw the text on the destination:
  SDL_BlitSurface( sText,NULL, sDest,&rc );
  SDL_FreeSurface( sText );
}
